﻿namespace ApiTemplate.Common
{
    /// <summary>
    /// 阿里云对象存储的操作类
    /// </summary>
    public class AliOSSHelper
    {
        /// <summary>
        /// 秘钥
        /// </summary>
        const string accessKeySecret = "Ni27tYm************jCa5buJnW";

        /// <summary>
        /// key
        /// </summary>
        const string accessKeyId = "LTAI*******nqv";

        /// <summary>
        /// 存储桶名称
        /// </summary>
        const string bucketName = "*****";

        /// <summary>
        /// 地址
        /// </summary>
        const string endpoint = "oss-cn-beijing.aliyuncs.com";

        /// <summary>
        /// 获取临时token
        /// </summary>
        /// <returns></returns>
        public static OssTokenOutput GetSTSToken()
        {
            DateTime now = DateTime.Now;
            DateTime ex = now.AddMinutes(Convert.ToDouble(10));
            PolicyConditions policyConds = new();
            policyConds.AddConditionItem("content-length-range", 0, 1048576000);
            OssClient client = new($"https://{endpoint}", accessKeyId, accessKeySecret);
            string postPolicy = client.GeneratePostPolicy(ex, policyConds);
            byte[] binaryData = Encoding.UTF8.GetBytes(postPolicy);
            string encodedPolicy = Convert.ToBase64String(binaryData);
            HMACSHA1 hmac = new(Encoding.UTF8.GetBytes(accessKeySecret));
            byte[] hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(encodedPolicy));
            string Signature = Convert.ToBase64String(hashBytes);
            OssTokenOutput output = new()
            {
                //AccessKeyId = accessKeyId,
                //AccessKeySecret = accessKeySecret,
                BucketName = bucketName,
                Endpoint = endpoint,
                Policy = encodedPolicy,
                Signature = Signature,
                Host = $"https://{bucketName}.{endpoint}",
                Expire = ex.ToString("s"),
                Guid = Guid.NewGuid().ToString()
            };
            return output;
        }

        /// <summary>
        /// 爬取图片上传到OSS
        /// </summary>
        /// <param name="fileUrl">文件路径</param>
        /// <param name="extension">文件扩展名</param>
        /// <param name="folder">要上传到的文件夹</param>
        /// <returns>OSS完整地址</returns>
        public static async Task<string> FileUploadForUrlAsync(string fileUrl, string extension = "png", string folder = "Excel")
        {
            var objectName = Guid.NewGuid().ToString();
            // 创建OssClient实例。
            var client = new OssClient(endpoint, accessKeyId, accessKeySecret);

            HttpClient httpClient = new(new SocketsHttpHandler()
            {
                AllowAutoRedirect = true,
                ConnectTimeout = new TimeSpan(0, 0, 10),
                UseCookies = false,
            });
            HttpResponseMessage response = await httpClient.GetAsync(fileUrl);
            Stream stream = await response.Content.ReadAsStreamAsync();
            string newName = $"{folder}/{objectName}.{extension}";
            // 上传文件。
            client.PutObject(bucketName, newName, stream);
            return $"https://{endpoint}/{newName}";
        }

        /// <summary>
        /// 上传文件至OSS
        /// </summary>
        /// <param name="stream">文件流</param>
        /// <param name="fileName">文件名</param>
        /// <param name="folder">文件夹</param>
        /// <returns>OSS完整地址</returns>
        public static string FileUploadForStream(Stream stream, string fileName, string folder = "Excel")
        {
            // 创建OssClient实例。
            var client = new OssClient(endpoint, accessKeyId, accessKeySecret);

            string newName = $"{folder}/{fileName}";
            // 上传文件。
            client.PutObject(bucketName, newName, stream);
            return $"https://{endpoint}/{newName}";
        }
    }

    /// <summary>
    /// OSStoken的输出对象
    /// </summary>
    public class OssTokenOutput
    {
        public string AccessKeyId { get; set; }

        public string AccessKeySecret { get; set; }

        public string BucketName { get; set; }

        public string Endpoint { get; set; }

        public string Policy { get; set; }

        public string Signature { get; set; }

        public string Host { get; set; }

        public string Expire { get; set; }

        public string Guid { get; set; }
    }
}
